package design_pattern.ReadWriteLock;

import com.sun.org.apache.xml.internal.resolver.readers.ExtendedXMLCatalogReader;

/**
 * @Author: 蔡翔
 * @Date: 2019/11/3 15:18
 * @Version 1.0
 */
public class ReadWriteLock {
    //不管是读还是写  waiting都在操作“操作之前”。
    private int readingReaders = 0;
    private int waitingReaders = 0;
    private int writingWriters = 0;
    private int waitingWriters = 0;

    private boolean preferWriter = true;
    public ReadWriteLock(){
        this(true);
    }
    public ReadWriteLock(boolean preferWriter){
        this.preferWriter = preferWriter;
    }

    // 读加锁解锁的 缘由是为了 ；防止在读的过程中 ，有另外程序要往这个“共享数据源”写数据。
    public synchronized void readLock() throws InterruptedException {
        this.waitingReaders++;
        try {
            //如果有人在写，，我就不能读了
            //注意这里是可以同时多个线程一起读的，比如我这里读，不对其他读者做限制。
            //终点设计偏爱吗，模式，不然read线程会一直抓着资源 不放。
            while (writingWriters>0 || (preferWriter && waitingWriters > 0)){
                this.wait();
            }
            //如果不写了 ，那我就去读。所以 readingReaders 就多了1
            this.readingReaders++;
        } finally {
            this.waitingReaders--;
        }
    }
    public synchronized void readUnlock(){
        this.readingReaders--;
        this.notifyAll();
    }



    public synchronized void writeLock() throws InterruptedException {
        this.waitingWriters++;
        try {
            while (readingReaders>0 || writingWriters>0){
                //当有线程在读，或者有线程在写，那么我只能歇着
                this.wait();
            }
            this.writingWriters++;
        }finally {
            this.waitingWriters--;
        }
    }

    public synchronized void writeUnlock(){
        this.writingWriters--;
        //唤醒所有在wait()的线程，下一个资源看谁分配到 就给谁。
        notifyAll();
    }
}
